package si.banst.tecajnice.ejb;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import si.banst.tecajnice.ejb.napake.NapacniArgumenti;
import si.banst.tecajnice.ejb.napake.NapakaPriPosodobitvi;
import si.banst.tecajnice.ejb.napake.NapakaPriPovprasevanju;
import si.banst.tecajnice.ejb.napake.NapakaPriPreracunu;
import si.banst.tecajnice.ejb.napake.NapakaPriZapisu;
import si.banst.tecajnice.ejb.prestrezniki.SledenjeZahtevam;
import si.banst.tecajnice.entitete.Ponder;
import si.banst.tecajnice.entitete.PonderID;
import si.banst.tecajnice.entitete.StatusAktivnosti;
import si.banst.tecajnice.entitete.Valuta;
import si.banst.tecajnice.entitete.VrstaTecajnice;

/**
 * Session Bean implementation class PonderjiBean
 */
@Stateless
@Interceptors(SledenjeZahtevam.class)
@RolesAllowed({ "OdgovorniReferent", "ReferentZaPreracun" })
public class PonderjiBean implements PonderjiBeanLocal, PonderjiBeanRemote {
	private static final Logger logger = Logger.getLogger(PonderjiBean.class
			.getName());

	@PersistenceContext(unitName = "tecajnice-jpa")
	private EntityManager em;

	@EJB
	private TecajniceBeanLocal tecajniceBean;

	@EJB
	private ValuteBeanLocal valuteBean;

	@EJB
	private PonderjiBeanLocal ponderjiBean;

	@Resource
	private SessionContext sessionContext;

	/**
	 * Default constructor.
	 */
	public PonderjiBean() {
		super();
	}

	@PostConstruct
	public void init() {
		logger.fine("Preverjam povezavos s persistečno enoto");
		if (em == null) {
			logger.severe("Povezava z persistencno enoto tecajnice-jpa ni vzpostavljena.");
			throw new EJBException(
					"Povezava z persistencno enoto tecajnice-jpa ni vzpostavljena.");
		}
	}

	@Override
	public List<Ponder> vrniVsePonderje() throws NapakaPriPovprasevanju {
		try {
			@SuppressWarnings("unchecked")
			List<Ponder> ponderji = em.createNamedQuery("vrniVsePonderje")
					.getResultList();
			logger.fine("Povpraševanje uspešno izvedeno.");
			return ponderji;
		} catch (Exception e) {
			logger.severe("Napaka pri povprasevanju." + e.getMessage());
			throw new NapakaPriPovprasevanju(e);
		}
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Ponder> vrniVseNeaktivnePonderje()
			throws NapakaPriPovprasevanju {
		try {
			Query povprasevanje = em
					.createNamedQuery("vrniVseNeaktivnePonderje");
			logger.fine("Povpraševanje uspešno izvedeno.");
			return povprasevanje.getResultList();
		} catch (Exception e) {
			logger.severe("Napaka pri povprasevanju." + e.getMessage());
			throw new NapakaPriPovprasevanju(e);
		}
	}

	@Override
	public Ponder vrniPonder(PonderID ponderID) throws NapacniArgumenti,
			NapakaPriPovprasevanju {
		try {
			Ponder ponder = em.find(Ponder.class, ponderID);
			logger.fine("Povpraševanje uspešno izvedeno.");
			return ponder;
		} catch (Exception e) {
			logger.severe("Napaka pri povprasevanju." + e.getMessage());
			throw new NapakaPriPovprasevanju(e);
		}
	}

	@Override
	public void zapisiPonder(Ponder ponder) throws NapakaPriZapisu {
		try {
			em.persist(ponder);
			logger.fine("Zapis uspešno vstavljen.");
		} catch (Exception e) {
			logger.severe("Napaka pri zapisovanju." + e.getMessage());
			throw new NapakaPriZapisu(e);
		}
	}

	@Override
	public void posodobiPonder(Ponder ponder) throws NapakaPriPosodobitvi {
		try {
			em.merge(ponder);
			logger.fine("Zapis uspešno posodobljen.");
		} catch (Exception e) {
			logger.severe("Napaka pri posodobitvi." + e.getMessage());
			throw new NapakaPriPosodobitvi(e);
		}
	}

	@Override
	@RolesAllowed({ "OdgovorniReferent" })
	public List<Ponder> zapisiVzorcnePonderje() throws NapakaPriPreracunu {
		try {
			logger.fine("Zapisujem vzorcne ponderje.");
			List<Ponder> seznamPreracunanihPonderjev = new ArrayList<Ponder>();
			List<VrstaTecajnice> seznamVrstTecajnic = tecajniceBean
					.vrniVseVrsteTecajnic();
			VrstaTecajnice vrstaTecajniceBSi = tecajniceBean
					.vrniVrstoTecajniceBSi();
			List<Valuta> seznamValut = valuteBean.vrniVseValute();

			int steviloPosodobljenihPonderjev = 0;
			int steviloZapisanihPonderjev = 0;

			for (VrstaTecajnice vrstaTecajnice : seznamVrstTecajnic) {
				if (vrstaTecajnice.equals(vrstaTecajniceBSi))
					continue;

				for (Valuta valuta : seznamValut) {

					PonderID ponderID = new PonderID();
					ponderID.setSifraValute(valuta.getSifraValute());
					ponderID.setSifraVrsteTecajnice(vrstaTecajnice
							.getSifraVrsteTecajnice());

					Ponder ponder = ponderjiBean.vrniPonder(ponderID);

					Boolean ponderZeOBstaja = true;
					if (ponder == null) {
						ponder = new Ponder();
						ponderZeOBstaja = false;
					}

					ponder.setId(ponderID);

					ponder.setDatumCasSpremembe(new Date());
					ponder.setReferent(sessionContext.getCallerPrincipal()
							.getName());
					ponder.setStatusAktivnosti(StatusAktivnosti.AKTIVEN);
					ponder.setValuta(valuta);
					ponder.setVrstaTecajnice(vrstaTecajnice);

					BigDecimal odmik = new BigDecimal(
							1.0 + (Math.random() * 0.2));
					ponder.setOdmikNakupnegaTecaja(odmik.setScale(4,
							BigDecimal.ROUND_HALF_UP));

					odmik = new BigDecimal(1.0 - (Math.random() * 0.2));
					ponder.setOdmikProdajnegaTecaja(odmik.setScale(4,
							BigDecimal.ROUND_HALF_UP));

					if (ponderZeOBstaja) {
						ponderjiBean.posodobiPonder(ponder);
						logger.fine("Ponder uspešno posodobljen. Vrsta tečajnice: "
								+ vrstaTecajnice.getNazivVrsteTecajnice()
								+ " Valuta: " + valuta.getOznakaValute());
						steviloPosodobljenihPonderjev++;
					} else {
						ponderjiBean.zapisiPonder(ponder);
						logger.fine("Ponder uspešno zapisan. Vrsta tečajnice: "
								+ vrstaTecajnice.getNazivVrsteTecajnice()
								+ " Valuta: " + valuta.getOznakaValute());
						steviloZapisanihPonderjev++;
					}
				}
			}
			logger.info("Ponderji uspešno zapisani. Število zapisanih ponderjev: "
					+ steviloZapisanihPonderjev
					+ " Število posodobljenih ponderjev: "
					+ steviloPosodobljenihPonderjev);
			return seznamPreracunanihPonderjev;
		} catch (Exception e) {
			logger.severe("Napaka pri preračunu ponderjev." + e.getMessage());
			throw new NapakaPriPreracunu("Napaka pri preračunu ponderjev", e);
		}

	}

	@Override
	public List<Ponder> vrniPonderje(List<PonderID> ponderID)
			throws NapacniArgumenti, NapakaPriPovprasevanju {
		List<Ponder> ponderji = new ArrayList<Ponder>();
		for (PonderID id : ponderID) {
			Ponder ponder = vrniPonder(id);
			if (ponder != null)
				ponderji.add(ponder);
		}
		return ponderji;
	}

	@Override
	public void posodobiPonderje(List<Ponder> ponderji)
			throws NapakaPriPosodobitvi {
		for (Ponder ponder : ponderji) {
			posodobiPonder(ponder);
		}

	}
}
